package br.com.winesys.geta;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Date;
import org.apache.commons.lang.WordUtils;
import br.com.winesys.geta.annotations.Caption;
import br.com.winesys.geta.annotations.Format;
import br.com.winesys.geta.annotations.TableColumn;
import br.com.winesys.geta.databinding.component.table.ColumnFactory;
import br.com.winesys.geta.databinding.component.table.TableModel;

final class TableModelBuilder {

    private TableModelBuilder() {
    }

    public static <T> TableModel<T> createTableModel(final Class<T> entityClass) {
        return new TableModel<T>() {

            @Override
            protected void createColumns() {
            	br.com.winesys.geta.annotations.TableModel tableModel = entityClass.getAnnotation(br.com.winesys.geta.annotations.TableModel.class);
            	if (tableModel != null){
            		for (int i = 0; i < tableModel.value().length; i++){
            			try {
            				TableColumn tableColumn = tableModel.value()[i];
							Field field = entityClass.getDeclaredField(tableColumn.field());
							Class<?> fieldClass = field.getType();
                            if (fieldClass.equals(Integer.class)) {
                            	Format format = field.getAnnotation(Format.class);
                            	if (format == null){
                                    addColumn(tableColumn.editable()
                                            ? ColumnFactory.createIntegerColumn(field.getName(), getDisplay(field), tableColumn.width())
                                            : ColumnFactory.createReadOnlyIntegerColumn(field.getName(), getDisplay(field), tableColumn.width()));
                            	} else {
                                    addColumn(tableColumn.editable()
                                            ? ColumnFactory.createIntegerColumn(field.getName(), getDisplay(field), tableColumn.width(), format.value())
                                            : ColumnFactory.createReadOnlyIntegerColumn(field.getName(), getDisplay(field), tableColumn.width(), format.value()));
                            	}
                            } else if (fieldClass.equals(Long.class)) {
                            	Format format = field.getAnnotation(Format.class);
                            	if (format == null){
                                    addColumn(tableColumn.editable()
                                            ? ColumnFactory.createLongColumn(field.getName(), getDisplay(field), tableColumn.width())
                                            : ColumnFactory.createReadOnlyLongColumn(field.getName(), getDisplay(field), tableColumn.width()));
                            	} else {
                                    addColumn(tableColumn.editable()
                                            ? ColumnFactory.createLongColumn(field.getName(), getDisplay(field), tableColumn.width(), format.value())
                                            : ColumnFactory.createReadOnlyLongColumn(field.getName(), getDisplay(field), tableColumn.width(), format.value()));
                            	}
                            } else if (fieldClass.equals(Float.class)) {
                                addColumn(tableColumn.editable()
                                        ? ColumnFactory.createFloatColumn(field.getName(), getDisplay(field), tableColumn.width(), getFormat(field))
                                        : ColumnFactory.createReadOnlyFloatColumn(field.getName(), getDisplay(field), tableColumn.width(), getFormat(field)));
                            } else if (fieldClass.equals(Double.class)) {
                                addColumn(tableColumn.editable()
                                        ? ColumnFactory.createDoubleColumn(field.getName(), getDisplay(field), tableColumn.width(), getFormat(field))
                                        : ColumnFactory.createReadOnlyDoubleColumn(field.getName(), getDisplay(field), tableColumn.width(), getFormat(field)));
                            } else if (fieldClass.equals(BigDecimal.class)) {
                                addColumn(tableColumn.editable()
                                        ? ColumnFactory.createBigDecimalColumn(field.getName(), getDisplay(field), tableColumn.width(), getFormat(field))
                                        : ColumnFactory.createReadOnlyBigDecimalColumn(field.getName(), getDisplay(field), tableColumn.width(), getFormat(field)));
                            } else if (fieldClass.equals(Date.class)) {
                                addColumn(tableColumn.editable()
                                        ? ColumnFactory.createDateColumn(field.getName(), getDisplay(field), tableColumn.width(), getFormat(field))
                                        : ColumnFactory.createReadOnlyDateColumn(field.getName(), getDisplay(field), tableColumn.width(), getFormat(field)));
                            } else if (fieldClass.equals(String.class)) {
                                addColumn(tableColumn.editable()
                                        ? ColumnFactory.createStringColumn(field.getName(), getDisplay(field), tableColumn.width())
                                        : ColumnFactory.createReadOnlyStringColumn(field.getName(), getDisplay(field), tableColumn.width()));
                            } else if (fieldClass.equals(Boolean.class)) {
                                addColumn(tableColumn.editable()
                                        ? ColumnFactory.createBooleanColumn(field.getName(), getDisplay(field), tableColumn.width())
                                        : ColumnFactory.createReadOnlyBooleanColumn(field.getName(), getDisplay(field), tableColumn.width()));
                            }
		                    } catch (Exception e) {
		                    	throw new RuntimeException("Unable to load field");
		                    }
            		}
            	}
            }
        };
    }
    
	private static String getDisplay(Field field) {
		Caption caption = field.getAnnotation(Caption.class);
		if (caption != null) {
			return caption.value();
		}
		return WordUtils.capitalize(field.getName());
	}
	
	private static String getFormat(Field field) {
		Format format = field.getAnnotation(Format.class);
		if (format != null){
			return format.value();
		}
		return "";
	}
}
